#ifndef USER_H
#define USER_H

#define ZEROPAD	1		/* pad with zero */
#define SIGN	2		/* unsigned/signed long */
#define PLUS	4		/* show plus */
#define SPACE	8		/* space if plus */
#define LEFT	16		/* left justified */
#define SMALL	32		/* Must be 32 == 0x20 */
#define SPECIAL	64		/* 0x */
#define NULL '\0'

#define DELAYNUM 512

#ifndef va_arg

#ifndef _VALIST
#define _VALIST
typedef char *va_list;
#endif				/* _VALIST */

/*
 * Storage alignment properties
 */
#define  _AUPBND                (sizeof (int) - 1)
#define  _ADNBND                (sizeof (int) - 1)

/*
 * Variable argument list macro definitions
 */
#define _bnd(X, bnd)            (((sizeof (X)) + (bnd)) & (~(bnd)))
#define va_arg(ap, T)           (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND))))
#define va_end(ap)              (void) 0
#define va_start(ap, A)         (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND))))

#endif				/* va_arg */
#define do_div(n,base) ({ int __res; __res = ((unsigned long) n) % (unsigned) base; n = ((unsigned long) n) / (unsigned) base; __res; })



int Strlen(const char *s)
{
    int i = 0;

    while (*s++)
        i++;
    return i;
}
char *Strcpy(char *dst, const char *src)
{
  char *cp = dst;
  while (*cp++ = *src++);
  return dst;
}


char *number(char *str, long num, int base, int type)
{
    /* we are called with base 8, 10 or 16, only, thus don't need "G..."  */
    static const char digits[17] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
    char tmp[66];
    char c, sign;
    int i;
    if (base < 2 || base > 36)
        return NULL;
    sign = 0;
    if (type & SIGN)
    {
        if (num < 0)
        {
            sign = '-';
            num = -num;
        }
        else if (type & PLUS)
        {
            sign = '+';
        }
        else if (type & SPACE)
        {

            sign = ' ';
        }
    }
    i = 0;
    if (num == 0)
    {
        tmp[i++] = '0';
    }
    else
        while (num != 0)
        {
            tmp[i++] = (digits[do_div(num, base)]);
        }
    if (sign)
        *str++ = sign;
    while (i-- > 0)
        *str++ = tmp[i];
    return str;
}

static  int isdigit(int ch)
{
	return (ch >= '0') && (ch <= '9');
}


int getNumFromInput(){
    char buf[2];
    int number;
    Read(buf, 2, ConsoleInput);
    number=strtint(buf);
    return number;
}


int Printf(const char *fmt, ...)
{
    char Printf_buf[128];
    va_list args;
    int printed;
    char * str;
    int base;
    int flags;
    int num;
    int len;
    int i;
    const char *s;
    va_start(args, fmt);
    for (str=Printf_buf ; *fmt ; ++fmt)
    {
        if (*fmt != '%')
        {
            *str++ = *fmt;
            continue;
        }
        flags = 0;
repeat:
        ++fmt;		/* this also skips first '%' */
        switch (*fmt)
        {
        case '-':
            flags |= LEFT;
            goto repeat;
        case '+':
            flags |= PLUS;
            goto repeat;
        case ' ':
            flags |= SPACE;
            goto repeat;
        case '#':
            flags |= SPECIAL;
            goto repeat;
        case '0':
            flags |= ZEROPAD;
            goto repeat;
        }
        base = 10;
        switch (*fmt)
        {
        case 'c':
            *str++ = (unsigned char) va_arg(args, int);
            continue;

        case 's':
            s = va_arg(args, char *);
            if (!s)
                s = "<NULL>";
            len = Strlen(s);
            for (i = 0; i < len; ++i)
                *str++ = *s++;
            continue;

        case '%':
            *str++ = '%';
            continue;

            /* integer number formats - set up the flags and "break" */
        case 'o':
            base = 8;
            break;
        case 'x':
            base = 16;
            break;
        case 'd':
        case 'i':
            flags |= SIGN;
        case 'u':
            break;

        default:
            *str++ = '%';
            if (*fmt)
                *str++ = *fmt;
            else
                --fmt;
            continue;
        }
        num = va_arg(args, unsigned int);
        if (flags & SIGN)
            num = (signed int) num;
        str = number(str, num, base, flags);
    }
    *str = '\0';
    va_end(args);
    printed=Strlen(Printf_buf);
    Write(Printf_buf,printed,ConsoleOutput);
    return printed;
}

/*end of Printf*/

int strtint(const char * cp){
    int value;
    int result = 0;
    while(*cp){
        if(!isdigit(*cp)){
            Printf("the words you put is not a digital number\n");
            return -1;
         }
       value =  *cp-'0';
       result=result*10+value;
            cp++;
    }
    return result;
}
/*if it is not a number, return -1, otherwise return the number*/

/*List operation*/

struct myList {
	void** array;
	int num;
	int lastItem;
	int firstItem;
};

void initialList(struct myList* theList, int listSize) {
	int i = 0;
	theList->num = listSize;
	theList->lastItem = -1;
	theList->firstItem = 0;
	for(i=0; i< theList->num; i++){
		theList->array[i] = NULL;
	}
}

void appendList (struct myList* theList, void* item) {
	(theList->lastItem) ++;
	if(theList->lastItem == theList->num) {
		theList->lastItem = 0;			
	}
	theList->array[theList->lastItem] = item;
}

void* removeList (struct myList* theList) {
	void* result;
	result = theList->array[theList->firstItem];
	(theList->firstItem) ++;
	if(theList->firstItem == theList-> num) {
		theList->firstItem = 0;
	}
	return result;

}

/*End of list operation*/

void delay(){
	int r;
	int i;
	r = 30000;
	for(i=0;i<r;i++){
		Yield();	
	}
}



#endif